package com.guoxin.part4.chapter18;

import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

/**
 * @author guoxin
 * @date 2019/8/31
 */
public class IntegerAccumulator {
    private int init;

    public IntegerAccumulator(int init) {
        this.init = init;
    }

    // 对初始值增加1
    public int add(int i) {
        this.init += i;
        return this.init;
    }

    // 返回当前初始值
    public int getValue() {
        return this.init;
    }

    public static void main(String[] args) {
        // 定义累加器，并且将设置初始值为0
        IntegerAccumulator accumulator = new IntegerAccumulator(0);
        // 定义3个线程，并且本别启动
        //        IntStream.range(0, 3).forEach(i -> {
        //            new Thread(() -> {
        //                int inc = 0;
        //                while (true) {
        //                    int oldValue = accumulator.getValue();
        //                    int result = accumulator.add(inc);
        //                    System.out.println(oldValue + "+" + inc + "=" + result);
        //                    if (inc + oldValue != result) {
        //                        System.err.println("ERROR:" + oldValue + "+" + inc + "=" + result);
        //                    }
        //                    inc++;
        //                    // 模拟延迟
        //                    slowly();
        //                }
        //            }).start();
        //        });

        IntStream.range(0, 3).forEach(i -> new Thread(() -> {
            int inc = 0;
            while (true) {
                int oldValue, result;
                // 使用class实例作为同步锁
                synchronized (IntegerAccumulator.class) {
                    oldValue = accumulator.getValue();
                    result = accumulator.add(inc);
                }
                System.out.println(oldValue + "+" + inc + "=" + result);
                if (inc + oldValue != result) {
                    System.err.println("ERROR:" + oldValue + "+" + inc + "=" + result);
                }
                inc++;
                // 模拟延迟
                slowly();
            }
        }).start());

    }

    private static void slowly() {
        try {
            TimeUnit.MILLISECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
